#include "door_common.h"
#include "gkt_backboard.h"
#include "gkt_debug.h"



#if defined(GKT_CONFIG_DOOR_LOCK_ENABLE) && GKT_CONFIG_DOOR_LOCK_ENABLE \
	&& defined(GKT_CONFIG_DOOR_LOCK_AUTOMATIC) && GKT_CONFIG_DOOR_LOCK_AUTOMATIC \
	&& defined(GKT_CONFIG_BACKBOARD_ENABLE) && GKT_CONFIG_BACKBOARD_ENABLE \
	&& (GKT_MODULE_LOC_BACKBOARD == GKT_DOOR_LOCK_LOCATION)

/* opcode */
enum {
	DOOR_LOCK_OP_OPEN = 0,
	DOOR_LOCK_OP_CLOSE,
	DOOR_LOCK_OP_SET_AUTO_CLOSE_TIME,
	DOOR_LOCK_OP_SET_MOTOR_ROTATE_TIME,
	DOOR_LOCK_OP_SET_MOTOR_ROTATE_DIRECTION,
	DOOR_LOCK_OP_SET_MOTOR_TORSION,
	DOOR_LOCK_OP_MOTOR_SELF_LEARNING,
	DOOR_LOCK_OP_SET_AUTO_DOUBLE_CLOSE_TIME,
	DOOR_LOCK_OP_SET_DOUBLE_CLOSE_MOTOR_ROTATE_TIME,
	DOOR_LOCK_OP_MAX
};

enum {
	DOOR_LOCK_COMMON_RSP_STATUS = GKT_BB_APP_PACKET_MINSIZE,
	DOOR_LOCK_COMMON_RSP_MAX
};

typedef struct _door_lock_auto_bb {
	int	init_ok;

	gkt_door_lock_body_type_e	body_type;
	uint32_t	motor_rotate_time;
	uint32_t	motor_full_rotate_time;
	uint32_t double_close_motor_rotate_time;

	uint32_t	status;
	int double_close;
	int	req_type;
	uint32_t	req_time_ms;

	gkt_door_notify_fn	notify;
} door_lock_auto_bb_s;
static door_lock_auto_bb_s s_door_lock_auto_bb;

uint32_t gkt_door_lock_get_status(void)
{
	return s_door_lock_auto_bb.status;
}

static int door_lock_check_req(int req_type)
{
	uint32_t maxtime, req_time_ms;

	gkt_info("door_lock: req_type(%d - %d), status(%u)\n", 
				s_door_lock_auto_bb.req_type, req_type, 
				s_door_lock_auto_bb.status);

	if (s_door_lock_auto_bb.req_type != DOOR_LOCK_REQ_MAX) {
		if (DOOR_LOCK_REQ_OPEN == s_door_lock_auto_bb.req_type)
			maxtime = s_door_lock_auto_bb.motor_full_rotate_time;
		else if (DOOR_LOCK_REQ_CLOSE == s_door_lock_auto_bb.req_type) {
			if (!s_door_lock_auto_bb.double_close)
				maxtime = s_door_lock_auto_bb.motor_rotate_time;
			else
				maxtime = s_door_lock_auto_bb.motor_full_rotate_time;
		}
		else {	/* (DOOR_LOCK_REQ_SLEF_LEARNING == s_door_lock_auto_bb.req_type) */
			maxtime = (s_door_lock_auto_bb.motor_full_rotate_time * 3)
				+ s_door_lock_auto_bb.motor_rotate_time;
		}
		maxtime += 100;

		req_time_ms = gkt_systime_ms();
		if ((s_door_lock_auto_bb.req_time_ms < req_time_ms)
			&& ((req_time_ms - s_door_lock_auto_bb.req_time_ms) >= maxtime)) 
		{
			s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
			return GKT_SUCCESS;
		}
		else if (s_door_lock_auto_bb.req_type == req_type)
			return GKT_EINPROCESS;
		else
			return GKT_EPERMIT;
	}

	return GKT_SUCCESS;
}

/*
 * 1. direct return from backboard_send_data
 * 2. local - notify if send failed (ACK timeout or others)
 * 3. peer - notify
 *    GKT_BB_STATUS_START : action start
 *    GKT_BB_STATUS_INPROCESS : action is already in process
 *    GKT_BB_STATUS_ERR_X : error occurs, params invalid, ...
 * 4. peer - notify
 *    GKT_BB_STATUS_COMPLETE : action complete
 *    GKT_BB_STATUS_ERR_X    : error occurs
 */
static void door_lock_open_module_notify(int type, 
				const uint8_t *data, int length_retval)
{
	uint8_t bb_status;
#if 0 //When the backboard presses the key, it will report the status to the backboard
	if (s_door_lock_auto_bb.req_type != DOOR_LOCK_REQ_OPEN) {
		gkt_error("door_lock_open_module_notify: <%d> not lock open req!\n", 
				s_door_lock_auto_bb.req_type);
		return;
	}
#endif
	if (GKT_BB_NOTIFY_PEER == type) {
		if (length_retval < DOOR_LOCK_COMMON_RSP_MAX) {
			gkt_error("door_lock_open_module_notify: <PEER> data length invalid!\n");
			return;
		}

		bb_status = data[DOOR_LOCK_COMMON_RSP_STATUS];
		gkt_info("door_lock_open_module_notify: <PEER> bb_status(%u)\n",
			bb_status);

		if ((GKT_BB_STATUS_START == bb_status)
			|| (GKT_BB_STATUS_INPROCESS == bb_status))
		{
			s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_OPENING;
			return;
		}
		else if ((GKT_BB_STATUS_SUCCESS == bb_status)
			|| (GKT_BB_STATUS_COMPLETE == bb_status)) 
		{
			s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_OPENED;
			s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
		}
		else if (bb_status >= GKT_BB_STATUS_ERR_BASE) {
			s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_OPEN_FAILED;
			s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
		}
		else
			return;
	}
	else if (length_retval < GKT_SUCCESS) {
		gkt_info("door_lock_open_module_notify: <LOCAL> retval(%d)\n",
			length_retval);
		s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_OPEN_FAILED;
		s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
	}
	else
		return;

	door_inner_notify(GKT_DOOR_NOTIFY_LOCK_STATUS, s_door_lock_auto_bb.status);
}
int gkt_door_lock_open(void)
{
	uint8_t open_lock_data[GKT_BB_APP_PACKET_MINSIZE];
	int retval;

	if (!s_door_lock_auto_bb.init_ok)
		return GKT_ENOTINIT;

	retval = door_lock_check_req(DOOR_LOCK_REQ_OPEN);
	if (GKT_SUCCESS == retval) {
		open_lock_data[GKT_BB_APP_PACKET_MODULE_ID] = GKT_BB_MODULE_DOOR_LOCK;
		open_lock_data[GKT_BB_APP_PACKET_OPCODE] = DOOR_LOCK_OP_OPEN;

		s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_OPEN;
		s_door_lock_auto_bb.req_time_ms = gkt_systime_ms();
		retval = gkt_backboard_send_data(open_lock_data, GKT_BB_APP_PACKET_MINSIZE);
		if ((GKT_SUCCESS == retval) || (GKT_EINPROCESS == retval))
			retval = GKT_EINPROCESS;
		else
			gkt_door_lock_reset();
	}

	return retval;
}

static void door_lock_close_module_notify(int type, 
				const uint8_t *data, uint32_t length_retval)
{
	uint8_t bb_status;
#if 0//Note the reasons as above
	if (s_door_lock_auto_bb.req_type != DOOR_LOCK_REQ_CLOSE) {
		gkt_error("door_lock_close_notify: <%d> not close req!\n", s_door_lock_auto_bb.req_type);
		return;
	}
#endif
	if (GKT_BB_NOTIFY_PEER == type) {
		if (length_retval < (GKT_BB_APP_PACKET_MINSIZE + 1)) {
			gkt_error("door_lock_close_notify: <PEER> data length invalid!\n");
			return;
		}
		
		bb_status = data[GKT_BB_APP_PACKET_MINSIZE];
		gkt_info("door_lock_close_notify: <PEER> status(%u), bb_status(%u)\n",
			s_door_lock_auto_bb.status, bb_status);

		if ((GKT_BB_STATUS_START == bb_status)
			|| (GKT_BB_STATUS_INPROCESS == bb_status))
		{
			s_door_lock_auto_bb.status = s_door_lock_auto_bb.double_close ?
				GKT_DOOR_LOCK_ST_DL_CLOSING : GKT_DOOR_LOCK_ST_CLOSING;
			return;
		}
		else if ((GKT_BB_STATUS_SUCCESS == bb_status)
			|| (GKT_BB_STATUS_COMPLETE == bb_status)) 
		{
			s_door_lock_auto_bb.status = s_door_lock_auto_bb.double_close ?
				GKT_DOOR_LOCK_ST_DL_CLOSED : GKT_DOOR_LOCK_ST_CLOSED;
			s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
		}
		else if (bb_status >= GKT_BB_STATUS_ERR_BASE) {
			s_door_lock_auto_bb.status = s_door_lock_auto_bb.double_close ?
				GKT_DOOR_LOCK_ST_DL_CLOSE_FAILED : GKT_DOOR_LOCK_ST_CLOSE_FAILED;
			s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
		}
		else
			return;
	}
	else if (length_retval < GKT_SUCCESS) {
		gkt_info("door_lock_close_notify: <LOCAL> status(%u), retval(%d)\n",
			s_door_lock_auto_bb.status, length_retval);
		s_door_lock_auto_bb.status = s_door_lock_auto_bb.double_close ?
			GKT_DOOR_LOCK_ST_DL_CLOSE_FAILED : GKT_DOOR_LOCK_ST_CLOSE_FAILED;
		s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
	}
	else
		return;

	door_inner_notify(GKT_DOOR_NOTIFY_LOCK_STATUS, s_door_lock_auto_bb.status);
}

enum {
	DOOR_LOCK_CLOSE_REQ_TYPE = GKT_BB_APP_PACKET_MINSIZE,
	DOOR_LOCK_CLOSE_REQ_MAX,
};
int gkt_door_lock_close(int double_close)
{
	uint8_t open_lock_data[DOOR_LOCK_CLOSE_REQ_MAX];
	int retval;

	if (!s_door_lock_auto_bb.init_ok)
		return GKT_ENOTINIT;

	retval = door_lock_check_req(DOOR_LOCK_REQ_CLOSE);
	if (GKT_SUCCESS == retval) {
		open_lock_data[GKT_BB_APP_PACKET_MODULE_ID] = GKT_BB_MODULE_DOOR_LOCK;
		open_lock_data[GKT_BB_APP_PACKET_OPCODE] = DOOR_LOCK_OP_CLOSE;
		open_lock_data[DOOR_LOCK_CLOSE_REQ_TYPE] = double_close ? 1 : 0;

		s_door_lock_auto_bb.double_close = double_close;
		s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_CLOSE;
		s_door_lock_auto_bb.req_time_ms = gkt_systime_ms();
		retval = gkt_backboard_send_data(open_lock_data, DOOR_LOCK_CLOSE_REQ_MAX);
		if ((GKT_SUCCESS == retval) || (GKT_EINPROCESS == retval))
			retval = GKT_EINPROCESS;
		else
			gkt_door_lock_reset();
	}

	return retval;
}

void gkt_door_lock_reset(void)
{
	if (s_door_lock_auto_bb.init_ok) {
		s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_MAX;
		s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
		s_door_lock_auto_bb.req_time_ms = 0;
	}
}

enum {
	DOOR_LOCK_SET_AUTO_CLOSE_TIME_REQ_TIME = GKT_BB_APP_PACKET_MINSIZE,
	DOOR_LOCK_SET_AUTO_CLOSE_TIME_REQ_MAX
};
enum {
	DOOR_LOCK_SET_AUTO_CLOSE_TIME_RSP_STATUS = GKT_BB_APP_PACKET_MINSIZE,
	DOOR_LOCK_SET_AUTO_CLOSE_TIME_RSP_MAX
};
int gkt_door_lock_set_auto_close_time(int double_close, uint32_t time)
{
	uint8_t data[DOOR_LOCK_SET_AUTO_CLOSE_TIME_REQ_MAX];
	int retval;

	if (!s_door_lock_auto_bb.init_ok)
		return GKT_ENOTINIT;

	if ((double_close && (time > GKT_DOOR_LOCK_AUTO_DOUBLE_CLOSE_TIME_MAX))
		|| (!double_close && ((time < GKT_DOOR_LOCK_AUTO_CLOSE_TIME_MIN) || (time > GKT_DOOR_LOCK_AUTO_CLOSE_TIME_MAX))))
	{
		retval = GKT_EPARAM;
	}
	else {
		data[GKT_BB_APP_PACKET_MODULE_ID] = GKT_BB_MODULE_DOOR_LOCK;
		data[GKT_BB_APP_PACKET_OPCODE] = (0 == double_close) ?
			DOOR_LOCK_OP_SET_AUTO_CLOSE_TIME : DOOR_LOCK_OP_SET_AUTO_DOUBLE_CLOSE_TIME;
		data[DOOR_LOCK_SET_AUTO_CLOSE_TIME_REQ_TIME] = (uint8_t)time;
		retval = gkt_backboard_send_data(data, DOOR_LOCK_SET_AUTO_CLOSE_TIME_REQ_MAX);
		if ((GKT_SUCCESS == retval) || (GKT_EINPROCESS == retval))
			retval = GKT_EINPROCESS;
	}

	return retval;
}

uint32_t gkt_door_lock_get_motor_rotate_time(gkt_door_lock_motor_rotate_time_e type)
{
	if (GKT_DOOR_LOCK_MOTOR_ROTATE_TIME_CLOSE == type)
		return s_door_lock_auto_bb.motor_rotate_time;
	else if (GKT_DOOR_LOCK_MOTOR_ROTATE_TIME_FULL == type)
		return s_door_lock_auto_bb.motor_full_rotate_time;
	else if (GKT_DOOR_LOCK_MOTOR_ROTATE_TIME_DOUBLE_CLOSE == type)
		return s_door_lock_auto_bb.double_close_motor_rotate_time;
	return 0;
}

enum {
	DOOR_LOCK_SET_MOTOR_ROTATE_TIME_REQ = GKT_BB_APP_PACKET_MINSIZE,
	DOOR_LOCK_SET_MOTOR_ROTATE_TIME_REQ_MAX
};
int gkt_door_lock_set_motor_rotate_time(gkt_door_lock_motor_rotate_time_e type, 
				uint32_t time_ms)
{
	int retval;
	uint8_t data[DOOR_LOCK_SET_MOTOR_ROTATE_TIME_REQ_MAX];

	if (!s_door_lock_auto_bb.init_ok)
		return GKT_ENOTINIT;

	retval = GKT_SUCCESS;
	if ((GKT_DOOR_LOCK_MOTOR_ROTATE_TIME_CLOSE == type) ||
		(GKT_DOOR_LOCK_MOTOR_ROTATE_TIME_DOUBLE_CLOSE == type))
	{
		if ((time_ms >= GKT_DOOR_LOCK_MOTOR_ROTATE_MINTIME_MS) &&
			(time_ms <= GKT_DOOR_LOCK_MOTOR_ROTATE_MAXTIME_MS))
		{
			s_door_lock_auto_bb.motor_rotate_time = time_ms;
			data[GKT_BB_APP_PACKET_MODULE_ID] = GKT_BB_MODULE_DOOR_LOCK;
			if (GKT_DOOR_LOCK_MOTOR_ROTATE_TIME_CLOSE == type)
				data[GKT_BB_APP_PACKET_OPCODE] = DOOR_LOCK_OP_SET_MOTOR_ROTATE_TIME;
			else
				data[GKT_BB_APP_PACKET_OPCODE] = DOOR_LOCK_OP_SET_DOUBLE_CLOSE_MOTOR_ROTATE_TIME;
			data[DOOR_LOCK_SET_MOTOR_ROTATE_TIME_REQ] = (uint8_t)(s_door_lock_auto_bb.motor_rotate_time/10);
			retval = gkt_backboard_send_data(data, DOOR_LOCK_SET_MOTOR_ROTATE_TIME_REQ_MAX);
			if ((GKT_SUCCESS == retval) || (GKT_EINPROCESS == retval))
				retval = GKT_EINPROCESS;
		}
	}
	else if ((GKT_DOOR_LOCK_MOTOR_ROTATE_TIME_FULL == type) 
		&& (time_ms >= GKT_DOOR_LOCK_MOTOR_FULL_ROTATE_MINTIME_MS)
		&& (time_ms <= GKT_DOOR_LOCK_MOTOR_FULL_ROTATE_MAXTIME_MS)) 
	{
		s_door_lock_auto_bb.motor_full_rotate_time = time_ms;
	}
	else
		retval = GKT_EPARAM;

	return retval;
}

enum {
	DOOR_LOCK_SET_MOTOR_ROTATE_DIRECTION_REQ_DIR = GKT_BB_APP_PACKET_MINSIZE,
	DOOR_LOCK_SET_MOTOR_ROTATE_DIRECTION_REQ_MAX
};
int gkt_door_lock_set_motor_rotate_direction(
				gkt_door_lock_motor_rotate_direction_e direction)
{
	uint8_t data[DOOR_LOCK_SET_MOTOR_ROTATE_DIRECTION_REQ_MAX];
	int retval = GKT_EPARAM;

	if (!s_door_lock_auto_bb.init_ok)
		return GKT_ENOTINIT;

	if (direction < GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION_MAX) {
		data[GKT_BB_APP_PACKET_MODULE_ID] = GKT_BB_MODULE_DOOR_LOCK;
		data[GKT_BB_APP_PACKET_OPCODE] = DOOR_LOCK_OP_SET_MOTOR_ROTATE_DIRECTION;
		data[DOOR_LOCK_SET_MOTOR_ROTATE_DIRECTION_REQ_DIR] = (uint8_t)direction;
		retval = gkt_backboard_send_data(data, DOOR_LOCK_SET_MOTOR_ROTATE_DIRECTION_REQ_MAX);
		if ((GKT_SUCCESS == retval) || (GKT_EINPROCESS == retval))
			retval = GKT_EINPROCESS;
	}

	return retval;
}

enum {
	DOOR_LOCK_SET_MOTOR_TORSION_REQ_GEAR = GKT_BB_APP_PACKET_MINSIZE,
	DOOR_LOCK_SET_MOTOR_TORSION_REQ_MAX
};
int gkt_door_lock_set_motor_torsion(
				gkt_door_lock_motor_torsion_gear_e gear)
{
	int retval = GKT_EPARAM;
	uint8_t data[DOOR_LOCK_SET_MOTOR_TORSION_REQ_MAX];

	if (!s_door_lock_auto_bb.init_ok)
		return GKT_ENOTINIT;

	if (gear < GKT_DOOR_LOCK_MOTOR_TORSION_GEAR_MAX) {
		data[GKT_BB_APP_PACKET_MODULE_ID] = GKT_BB_MODULE_DOOR_LOCK;
		data[GKT_BB_APP_PACKET_OPCODE] = DOOR_LOCK_OP_SET_MOTOR_TORSION;
		data[DOOR_LOCK_SET_MOTOR_TORSION_REQ_GEAR] = (uint8_t)gear;
		retval = gkt_backboard_send_data(data, DOOR_LOCK_SET_MOTOR_TORSION_REQ_MAX);
		if ((GKT_SUCCESS == retval) || (GKT_EINPROCESS == retval))
			retval = GKT_EINPROCESS;
	}

	return retval;
}

enum {
	DOOR_LOCK_MOTOR_SELF_LEARN_RSP_STATUS = GKT_BB_APP_PACKET_MINSIZE,
	DOOR_LOCK_MOTOR_SELF_LEARN_RSP_BODY_TYPE,
	DOOR_LOCK_MOTOR_SELF_LEARN_RSP_MAX
};
static void door_lock_motor_self_learn_module_notify(int type, 
				const uint8_t *data, int length_retval)
{
	uint8_t bb_status;

	if (s_door_lock_auto_bb.req_type != DOOR_LOCK_REQ_SLEF_LEARNING) {
		gkt_error("door_lock_motor_self_learn_notify: <%d> not slef learn req!\n", s_door_lock_auto_bb.req_type);
		return;
	}

	if (GKT_BB_NOTIFY_PEER == type) {
		if (length_retval <= DOOR_LOCK_MOTOR_SELF_LEARN_RSP_STATUS) {
			gkt_error("door_lock_motor_self_learn_notify: <PEER-0> data length invalid!\n");
			return;
		}

		bb_status = data[DOOR_LOCK_MOTOR_SELF_LEARN_RSP_STATUS];
		gkt_info("door_lock_motor_self_learn_notify: <PEER> bb_status(%u)\n", bb_status);

		if ((GKT_BB_STATUS_START == bb_status)
			|| (GKT_BB_STATUS_INPROCESS == bb_status))
		{
			s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_SELF_LEARNING;
			return;
		}
		else if ((GKT_BB_STATUS_SUCCESS == bb_status)
			|| (GKT_BB_STATUS_COMPLETE == bb_status)) 
		{
			if (length_retval >= (DOOR_LOCK_MOTOR_SELF_LEARN_RSP_MAX)) {
				s_door_lock_auto_bb.body_type = 
					data[DOOR_LOCK_MOTOR_SELF_LEARN_RSP_BODY_TYPE];
				s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_SELF_LEARN_COMPLETE;
				s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;

				gkt_printf("door_lock_motor_self_learn_notify: body(%u)\n",
					s_door_lock_auto_bb.body_type);
			}
			else {
				s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_SELF_LEARN_FAILED;
				s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
				gkt_error("door_lock_motor_self_learn_notify: <PEER-1> data length invalid!\n");
			}
		}
		else if (bb_status >= GKT_BB_STATUS_ERR_BASE) {
			s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_SELF_LEARN_FAILED;
			s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
		}
		else
			return;
	}
	else if (length_retval < GKT_SUCCESS) {
		s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_SELF_LEARN_FAILED;
		s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
		gkt_info("door_lock_motor_self_learn_notify: <LOCAL> retval(%d)\n", length_retval);
	}
	else
		return;

	door_inner_notify(GKT_DOOR_NOTIFY_LOCK_STATUS, s_door_lock_auto_bb.status);
}

/* MOTOR SELF LEAR REQ - NO ADDITIONAL DATA */
int gkt_door_lock_motor_self_learn(void)
{
	uint8_t data[GKT_BB_APP_PACKET_MINSIZE];
	int retval;

	if (!s_door_lock_auto_bb.init_ok)
		return GKT_ENOTINIT;

	retval = door_lock_check_req(DOOR_LOCK_REQ_SLEF_LEARNING);
	if (GKT_SUCCESS == retval) {
		data[GKT_BB_APP_PACKET_MODULE_ID] = GKT_BB_MODULE_DOOR_LOCK;
		data[GKT_BB_APP_PACKET_OPCODE] = DOOR_LOCK_OP_MOTOR_SELF_LEARNING;

		s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_SLEF_LEARNING;
		s_door_lock_auto_bb.req_time_ms = gkt_systime_ms();
		retval = gkt_backboard_send_data(data, GKT_BB_APP_PACKET_MINSIZE);
		if ((GKT_SUCCESS == retval) || (GKT_EINPROCESS == retval))
			retval = GKT_EINPROCESS;
		else
			gkt_door_lock_reset();
	}

	return retval;
}

gkt_door_lock_body_type_e gkt_door_lock_get_body_type(void)
{
	return s_door_lock_auto_bb.body_type;
}

uint32_t gkt_door_lock_get_timeout(gkt_door_lock_op_e op)
{
	uint32_t timeout;

	if ((GKT_DOOR_LOCK_OP_OPEN == op)
		|| (GKT_DOOR_LOCK_OP_DOUBLE_CLOSE == op))
	{
		timeout = s_door_lock_auto_bb.motor_full_rotate_time;
	}
	else if (GKT_DOOR_LOCK_OP_CLOSE == op)
		timeout = s_door_lock_auto_bb.motor_rotate_time;
	else if (GKT_DOOR_LOCK_OP_SELF_LEARN == op) {
		timeout = (s_door_lock_auto_bb.motor_full_rotate_time * 3)
			+ s_door_lock_auto_bb.motor_rotate_time;
	}
	else
		timeout = 0;

	return timeout;
}

static void door_lock_module_notify(int type, 
				const uint8_t *data, int length_retval)
{
	uint8_t opcode, bb_status;

	opcode = data[GKT_BB_APP_PACKET_OPCODE];
	if (DOOR_LOCK_OP_OPEN == opcode)
		door_lock_open_module_notify(type, data, length_retval);
	else if (DOOR_LOCK_OP_CLOSE == opcode)
		door_lock_close_module_notify(type, data, length_retval);
	else if (DOOR_LOCK_OP_MOTOR_SELF_LEARNING == opcode)
		door_lock_motor_self_learn_module_notify(type, data, length_retval);
	else {
		if (GKT_BB_NOTIFY_PEER == type) {
			if (length_retval < DOOR_LOCK_COMMON_RSP_STATUS)
				return;

			bb_status = data[DOOR_LOCK_COMMON_RSP_STATUS];
			gkt_info("door_lock_module_notify: <PEER> bb_status(%u)\n", bb_status);

			if (GKT_BB_STATUS_SUCCESS == bb_status)
				length_retval = GKT_SUCCESS;
			else if (bb_status >= GKT_BB_STATUS_ERR_BASE) {
				gkt_error("door_lock_module_notify: <PEER> ERROR - bb_status(%u)\n", bb_status);
				length_retval = GKT_ELOWLEVEL;
			}
			else
				return;
		}
		else if (length_retval < GKT_SUCCESS) {	/* local */
			gkt_error("door_lock_module_notify: <LOCAL> opcode(%u) failed %d\n",
				opcode, length_retval);
		}
		else
			return;

		door_inner_notify(GKT_DOOR_NOTIFY_LOCK_CONFIG, (uint32_t)length_retval);
	}
}
void gkt_door_lock_standby(void)
{
	//door_lock_motor_standby();
}
int door_lock_init(void)
{
	s_door_lock_auto_bb.init_ok = 0;
	s_door_lock_auto_bb.body_type = GKT_DOOR_LOCK_BODY_TYPE_NORMAL;
	s_door_lock_auto_bb.motor_rotate_time = GKT_DOOR_LOCK_MOTOR_ROTATE_TIME_MS;
	s_door_lock_auto_bb.motor_full_rotate_time = GKT_DOOR_LOCK_MOTOR_FULL_ROTATE_TIME_MS;
	s_door_lock_auto_bb.status = GKT_DOOR_LOCK_ST_MAX;
	s_door_lock_auto_bb.double_close = 0;
	s_door_lock_auto_bb.req_type = DOOR_LOCK_REQ_MAX;
	s_door_lock_auto_bb.notify = NULL;

	gkt_backboard_register_module(GKT_BB_MODULE_DOOR_LOCK,
			DOOR_LOCK_OP_MAX, door_lock_module_notify);

	s_door_lock_auto_bb.init_ok = 1;

	return GKT_SUCCESS;	
}

#endif

